package nz.co.listit.TaxiValet;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class LoginActivity extends ListItResClient {
	private EditText _etUsername;
	private EditText _etPassword;
	private String _c2dmEmail;
	private TextView _deviceIDDisplay;

	private void obtainC2DMEmail() {
		// get the C2DM email from the server
		_progDlg = ProgressDialog.show(this, "",
				"Obtaining information from the server. Please wait...", true);

		// call the List-it web service
		new Thread(new Runnable() {
			public void run() {
				ListItServerClient ltClient = new ListItServerClient();
				List<NameValuePair> qparams = new ArrayList<NameValuePair>();

				// call web service
				JSONObject result = ltClient.queryListItService("GetC2DMEmail",
						qparams);

				int retCode;
				try {
					retCode = result.getInt(KEY_SERVER_RET_CODE);

					// if the return code is not OK, it means we have comms
					// error so ask the user if they want to try again
					if (retCode != WEBSERVER_MESSAGES.OK.ordinal()) {
						if (_progDlg != null)
							_progDlg.dismiss();

						// show alert dialog
						LoginActivity.this.runOnUiThread(new Runnable() {

							public void run() {
								AlertDialog.Builder builder = new AlertDialog.Builder(
										LoginActivity.this);
								builder.setMessage(
										"Ops something went wrong while communicating with the server. Do you want to try again?")
										.setTitle("Cannot obtain information")

										.setCancelable(false)

										.setPositiveButton(
												"Yes",
												new DialogInterface.OnClickListener() {
													public void onClick(
															DialogInterface dialog,
															int d) {
														LoginActivity.this
																.obtainC2DMEmail();
													}

												})
										.setNegativeButton(
												"No",
												new DialogInterface.OnClickListener() {
													public void onClick(
															DialogInterface dialog,
															int whichButton) {
														// cannot continue
														// at
														// this point. Let's
														// close the
														// application
														dialog.cancel();
														LoginActivity.this
																.finish();
													}
												});

								AlertDialog alert = builder.create();
								alert.show();
							}
						});
					}

					Message msg = new Message();
					msg.what = retCode;
					msg.obj = result;
					LoginActivity.this.handler.sendMessage(msg);

				} catch (JSONException e) {
					Log.e(TAG, String.format(FMT_ERROR, "obtainC2DMEmail",
							KEY_SERVER_RET_CODE));
				}

			}
		}).start();
	}

	/**
	 * Embed a receiver so we can be notified when the C2DM registration is
	 * successful. If successful, then we can display the StatusActivity
	 */
	private BroadcastReceiver c2mdRegisteredReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (LoginActivity.this._progDlg != null)
				LoginActivity.this._progDlg.dismiss();

			String c2dmAction = intent.getAction();

			if (c2dmAction.equals(ListItC2dmReceiver.INTENT_C2DM_REGISTERED)) {
				if (LoginActivity.this._progDlg != null)
					LoginActivity.this._progDlg.dismiss();

				LoginActivity.this.showDriverStatus();
				LoginActivity.this.finish();
			} else {
				String errorMessage = "";

				if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_ACCOUNT_MISSING)) {
					errorMessage = "Google account not found. Please add a google account to your device.";
				} else if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_AUTHENTICATION_FAILED)) {
					errorMessage = "C2DM authentication failed.";
				} else if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_INVALID_SENDER)) {
					errorMessage = "Invalid C2DM sender.";
				} else if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_PHONE_REGISTRATION_ERROR)) {
					errorMessage = "C2DM phone registration error.";
				} else if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_SERVICE_NOT_AVAILABLE)) {
					errorMessage = "C2DM service is currently not available.";
				} else if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_TOO_MANY_REGISTRATIONS)) {
					errorMessage = "Too many C2DM registrations.";
				} else if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_UKNOWN_STATE)) {
					errorMessage = "Error! Unknown State.";
				} else if (c2dmAction
						.equals(ListItC2dmReceiver.INTENT_C2DM_UNREGISTERED)) {
					errorMessage = "List-it email is not registered for C2DM";
				}

				// inform the user that we cannot continue
				AlertDialog.Builder builder = new AlertDialog.Builder(
						LoginActivity.this);
				builder.setMessage(errorMessage).setTitle("C2DM error")

				.setCancelable(false)

				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int d) {
						dialog.cancel();
					}
				});

				AlertDialog alert = builder.create();
				alert.show();
			}
		}
	};

	private void showDriverStatus() {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		Bundle bundle = new Bundle();
		bundle.putBoolean("isBusy", false);
		bundle.putBoolean(KEY_SERVER_DEBUG_TAXI, _debug);
		intent.setClassName(this, StatusActivity.class.getName());
		intent.putExtras(bundle);
		LoginActivity.this.startActivity(intent);
	}

	/* Web Server Events */

	protected void onOKResult(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		try {
			_c2dmEmail = json.getString(KEY_SERVER_C2DM_EMAIL);
			// _c2dmEmail = "foo@gmail.com";
		} catch (JSONException e) {
			Log.e(TAG, String.format(FMT_ERROR, "onOKResult",
					KEY_SERVER_C2DM_EMAIL));
		}

		// now we can log in
	}

	@Override
	// called on ON_LOGGED_IN
	protected void onLoggedIn(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss(); // close previous progress bar first

		_progDlg = ProgressDialog.show(LoginActivity.this, "",
				"Registering for C2DM. Please wait...", true);

		// first we must register for C2DM
		Intent registrationIntent = new Intent(
				"com.google.android.c2dm.intent.REGISTER");
		registrationIntent.putExtra("app",
				PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate
		registrationIntent.putExtra("sender", _c2dmEmail);

		try {
			this.startService(registrationIntent);
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
	}

	@Override
	// called on INVALID_USERNAME
	protected void onInvalidUsername(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		try {
			this.showError("", json.getString(KEY_SERVER_MESSAGE));
			_etUsername.requestFocus();
		} catch (JSONException e) {
			Log.e(TAG, String.format(FMT_ERROR, "onInvalidUsername",
					KEY_SERVER_MESSAGE));
		}
	}

	@Override
	// called on INVALID_PASSWORD
	protected void onInvalidPassword(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		try {
			this.showError("", json.getString(KEY_SERVER_MESSAGE));
			_etPassword.requestFocus();
		} catch (JSONException e) {
			Log.e(TAG, String.format(FMT_ERROR, "onInvalidPassword",
					KEY_SERVER_MESSAGE));
		}
	}

	@Override
	// called on UNREGISTERED_DEVICE
	protected void onUnRegisteredDevice(JSONObject json) {
		if (_progDlg != null)
			_progDlg.dismiss();

		this.showError("Device not registered",
				"Your device is not registered. Please contact List-It");
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login);

		_etUsername = (EditText) findViewById(R.id.etUsername);
		_etPassword = (EditText) findViewById(R.id.etPassword);
		_deviceIDDisplay = (TextView) findViewById(R.id.tvDeviceID);

		_deviceIDDisplay.setText(this.getDeviceID());
		// _deviceIDDisplay.setText(this.getLocalIpAddress());

		/*
		 * This is a pre-requisite before we can allow the user to login.
		 * Without the C2DM email we can't register for C2DM, and without a C2DM
		 * key we can't receive job notifications.
		 */
		obtainC2DMEmail();
	}

	@Override
	public void onResume() {
		super.onResume();

		// register for C2DM actions
		IntentFilter filter = new IntentFilter();
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_ACCOUNT_MISSING);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_AUTHENTICATION_FAILED);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_INVALID_SENDER);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_PHONE_REGISTRATION_ERROR);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_REGISTERED);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_SERVICE_NOT_AVAILABLE);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_TOO_MANY_REGISTRATIONS);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_UNREGISTERED);
		filter.addAction(ListItC2dmReceiver.INTENT_C2DM_UKNOWN_STATE);

		this.registerReceiver(c2mdRegisteredReceiver, filter);
	}

	@Override
	public void onStart() {
		super.onStart();
	}

	@Override
	protected void onDestroy() {
		unregisterReceiver(c2mdRegisteredReceiver);

		super.onDestroy();
	}

	public void onLoginClick(View v) {
		// the progress dlg need to be invoked here and not inside the
		// thread below
		_progDlg = ProgressDialog.show(LoginActivity.this, "",
				"Communicating to List-It Server. Please wait...", true);

		// now login to List-It server
		Thread thread = new Thread(LoginActivity.this);
		thread.start();
	}

	@Override
	public void run() {
		ListItServerClient ltClient = new ListItServerClient();

		List<NameValuePair> qparams = new ArrayList<NameValuePair>();

		Message msg = new Message();

		try {
			// add device ID
			qparams.add(new BasicNameValuePair("deviceID", this.getDeviceID()));

			// add C2DM token
			qparams.add(new BasicNameValuePair("deviceToken",
					ListItC2dmReceiver.getC2DMRegistrationKey(this)));

			// add username
			qparams.add(new BasicNameValuePair("username", _etUsername
					.getText().toString()));

			// add password
			qparams.add(new BasicNameValuePair("password", _etPassword
					.getText().toString()));

			// call web service
			JSONObject result = ltClient.queryListItService(
					"Pagsusuri9S5T67KJHoiil56", qparams);

			msg.what = result.getInt(KEY_SERVER_RET_CODE);
			msg.obj = result;

			// check is the server wants us to be in debug mode
			if (result.has(KEY_SERVER_DEBUG_TAXI))
				LoginActivity.this._debug = result
						.getBoolean(KEY_SERVER_DEBUG_TAXI);

			handler.sendMessage(msg);

		} catch (JSONException e) {
			handler.sendMessage(msg);
		}
	}
}
